package server;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.net.*;
import java.io.*;
import java.util.ArrayList;

public class Server {
    ServerSocket serverSocket;
    public static void main (String [] args ) { 
        try {
            // create socket 
                Server server = new Server();
                ServerSocket serverSocket= server._ConnectSocket(5217);
                System.out.println("Waiting for Connection on Port 5217...");
                while(true){
                        //Thread.sleep(5000);
                    new ProcessFile(serverSocket.accept()).start();
                }
        } catch (IOException ex) {}
    }
    
    public ServerSocket _ConnectSocket(int port)
    {
        try {
            return new ServerSocket(port);
        } catch (IOException ex) {
        }
        return null;
    }
}

class ProcessFile extends Thread {
    
    protected int id;
    protected Socket sock;
    protected DataInputStream in;
    protected DataOutputStream out;
    private BufferedOutputStream bos=null;
    private BufferedInputStream bis=null;
    public ProcessFile(Socket sock){
        try {
            this.sock = sock;
            out = new DataOutputStream(sock.getOutputStream());
            in = new DataInputStream(sock.getInputStream());
            System.out.println("Client "+sock.getInetAddress()+" is connecting");
        } catch (IOException ex) {
        }
    }
      
    @Override
    public void run() {
        try {
            //read file 
            switch(in.readUTF())
            {
                case "S":
                    this.ReceiveFile();
                    break;
                case "G":
                    id=Integer.parseInt(in.readUTF());
                    ArrayList<File> listFiles= listFilesForFolder(new File("C:\\File"));
                    out.writeInt(listFiles.size());
                    if(listFiles.size()>0)
                    {             
                        for(File f : listFiles)
                        {
                            SendFile(f);                  
                        }
                    }
                    break;
                default:
                    break;
            }
        } catch (IOException ex) {
            System.out.println("Error: "+ex.getMessage());
        }
        finally{
            try {
                in.close();
                out.close();
                sock.close();
                if(bos!=null)
                {
                    bos.flush();
                    bos.close();
                }
                if(bis!=null)
                {
                    bis.close();
                }
                System.out.println("Disconnect from: "+sock.getInetAddress()+"");
            } catch (IOException ex) {
                System.out.println("Error: "+ex.getMessage());
            }
        }
      }
    
    public void ReceiveFile()
    {
        try {
            String fileName = "C:\\File\\"+System.currentTimeMillis()+".khn";
            //Receive file
            if(in.readUTF().compareTo("Fileinvalid")==0)
            {
                return;
            }
            byte [] bytearray  = new byte [1024*10];
            FileOutputStream fos = new FileOutputStream(fileName,true);
            bos = new BufferedOutputStream(fos);
            
            int n=-1;
            int rn=0;
            long start = System.currentTimeMillis();
            while ((n = in.read(bytearray)) > -1){
                fos.write(bytearray, 0, n);
                rn+=n;
            }
            
            long end = System.currentTimeMillis();
            System.out.println("Receive successfuly "+(float)rn/1000 + " bytes written in " + (end-start)/1000 + " s.");
        } catch (SocketException ex) {
            System.out.println("Error: "+ex.getMessage());
        }catch(IOException ex){
        
        }finally {}
    }
    
    public void SendFile(File transferFile) throws IOException
    {
        FileInputStream fis = null;
        try {
            out = new DataOutputStream(sock.getOutputStream());
            out.writeUTF(transferFile.getName());
            out.flush();
            if(!transferFile.exists())
            {
                      System.out.println("File invalid");
                      out.writeUTF("Fileinvalid");
                      return;
            }
            else out.writeUTF("Filevalid");
            
            fis = new FileInputStream(transferFile);
            byte [] bytearray  = new byte [1024*10];
            bis = new BufferedInputStream(fis);
            int fileSize= fis.available();
            out.writeInt(fileSize);
            out.flush();
            System.out.println("Sending to "+sock.getInetAddress()+" -- File: "+transferFile.toString()+" -- Size: "+fileSize/1000+" Kb");
            int c=-1;
            long start = System.currentTimeMillis();
            while((c = bis.read(bytearray,0,bytearray.length)) != -1)
            {
                      out.write(bytearray, 0, c);
                      fileSize -= c;
                      //System.out.printf("Remaining %.2f Kb %n",(float)size/1024);
            }
            
            out.flush();
            if(fileSize<=0)
                System.out.println("File transfer complete in: "+(System.currentTimeMillis()-start)/1000 + " s.\n");
        } catch (FileNotFoundException ex) {
        }
    }
    
    public ArrayList<File> listFilesForFolder(final File folder) {
        long timeStamp =folder.lastModified();
        ArrayList<File> files = new ArrayList<>();
        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                fileEntry.getName();
                listFilesForFolder(fileEntry);
            } else {
                files.add(fileEntry);
            }
        }
        return files;
    }
}
